package com.lz.autotest.project.testmanage.reportmanage.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.lz.autotest.common.constant.CompareTypeConstants;
import com.lz.autotest.common.entity.ResponseVo;
import com.lz.autotest.project.testmanage.infmanage.domain.InfItemResult;
import com.lz.autotest.project.testmanage.reportmanage.domain.ReportItem;
import com.lz.autotest.project.testmanage.infmanage.domain.SstInf;
import com.lz.autotest.project.testmanage.reportmanage.domain.SstReportItem;
import com.lz.autotest.project.testmanage.infmanage.service.InfManageService;
import com.lz.autotest.project.testmanage.reportmanage.service.InfReportService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: X
 * @date: Created in 2023/8/18 10:25
 * @Description:
 */
@RestController
@RequestMapping("compare")
public class CompareController {

    @Resource
    private InfReportService infReportService;
    @Resource
    private InfManageService infManageService;

    @PostMapping("/compare.action")
    @PreAuthorize("@ss.hasPermi('testmanage:compareResult:compare')")
    public ResponseVo compare(@RequestBody List<String> ids) {
        ResponseVo check = check(ids);
        if (!check.isSuccess()) {
            return check;
        }
        List<SstReportItem> items = (List<SstReportItem>) check.getResult();

        Map<String, List<ReportItem>> map = getAllInfMap(items);

        List<InfItemResult> list1 = items.get(0).getList();
        List<InfItemResult> list2 = items.get(1).getList();

        List<InfItemResult> miss1 = compareByType(list1, list2, CompareTypeConstants.MISS);
        List<InfItemResult> miss2 = compareByType(list2, list1, CompareTypeConstants.MISS);
        List<InfItemResult> sames = compareByType(list1, list2, CompareTypeConstants.SAME);

        Map<String, Object> resp = compareResult(list1, list2, sames);
        if (miss1.size() > 0) {
            List<String> collect = miss1.stream().map(InfItemResult::getInfId)
                    .collect(Collectors.toList());
            resp.put(items.get(1).getReportName(), collect);
        }
        if (miss2.size() > 0) {
            List<String> collect = miss2.stream().map(InfItemResult::getInfId)
                    .collect(Collectors.toList());
            resp.put(items.get(0).getReportName(), collect);
        }
        List<SstInf> sstInfs = new ArrayList<>();
        for (String value : resp.keySet()) {
            List<SstInf> list = infManageService.selectInfListByIds((List<String>) resp.get(value));
            if (value.equals("different")) {
                for (SstInf sstInf : list) {
                    sstInf.setCompareResult("2");
                    sstInf.setResultList(map.get(sstInf.getInfId()));
                    sstInf.setCompareMsg("结果不一致");
                }
            } else if (value.equals("same")) {
                for (SstInf sstInf : list) {
                    sstInf.setCompareResult("1");
                    sstInf.setResultList(map.get(sstInf.getInfId()));
                    sstInf.setCompareMsg("结果一致");
                }
            } else {
                for (SstInf sstInf : list) {
                    sstInf.setCompareResult("0");
                    sstInf.setResultList(map.get(sstInf.getInfId()));
                    sstInf.setCompareMsg(value + "缺少接口结果");
                }
            }
            sstInfs.addAll(list);
        }
        return ResponseVo.success(sstInfs);
    }

    /**
     * @description 作比较时做基本的检查
     * @author zip.li
     * @date 2023/8/21 14:19
     * @Version1.0
     **/
    public ResponseVo check(List<String> ids) {
        if (ids.size() != 2) {
            return ResponseVo.failure("超过两个报告无法比较");
        }

        List<SstReportItem> items = infReportService.queryReportItemByIds(ids);

        try {
            for (SstReportItem item : items) {
                JSONArray objects = JSON.parseArray(item.getResult());
                List<InfItemResult> infItemResults = objects.toJavaList(InfItemResult.class);
                item.setList(infItemResults);
            }
            return ResponseVo.success(items);
        } catch (Exception e) {
            return ResponseVo.failure("结果格式错误无法比较");
        }
    }

    /**
     * @description 获取所有的接口集合
     * @author zip.li
     * @date 2023/8/21 15:06
     * @Version1.0
     **/
    public Map<String, List<ReportItem>> getAllInfMap(List<SstReportItem> items) {
        HashSet<String> set = new HashSet<>();
        Map<String, List<ReportItem>> map = new HashMap<>();
        //获取所有的接口，并去重
        for (SstReportItem item : items) {
            for (InfItemResult infItemResult : item.getList()) {
                set.add(infItemResult.getInfId());
            }
        }
        //确保所有的List中都有对应报告的对象
        for (String infId : set) {
            List<ReportItem> list = new ArrayList<>();
            for (SstReportItem item : items) {
                ReportItem reportItem = new ReportItem();
                reportItem.setReportName(item.getReportName());
                reportItem.setVersion(item.getReportVersion());
                list.add(reportItem);
            }
            map.put(infId, list);
        }
        //将有结果的放入List中
        for (SstReportItem item : items) {
            for (InfItemResult infItemResult : item.getList()) {
                List<ReportItem> list = map.get(infItemResult.getInfId());
                for (ReportItem reportItem : list) {
                    if (reportItem.getReportName().equals(item.getReportName())) {
                        reportItem.setResult(infItemResult.getResult());
                    }
                }
            }
        }
        return map;
    }


    /**
     * @description 根据比较方法获取结果
     * @author zip.li
     * @date 2023/8/17 10:43
     * @Version1.0
     **/
    public List<InfItemResult> compareByType(List<InfItemResult> list1, List<InfItemResult> list2, String type) {
        List<InfItemResult> result = new ArrayList<>();
        switch (type) {
            case CompareTypeConstants.SAME:
                List<String> list = list1.stream()
                        .map(InfItemResult::getInfId)
                        .filter(infId -> list2.stream().anyMatch(person -> person.getInfId().equals(infId)))
                        .collect(Collectors.toList());
                for (String infId : list) {
                    InfItemResult infItemResult = new InfItemResult(infId);
                    result.add(infItemResult);
                }
                break;
            case CompareTypeConstants.MISS:
                result = list1.stream()
                        .filter(person1 ->
                                list2.stream().noneMatch(person2 -> person2.getInfId().equals(person1.getInfId())))
                        .collect(Collectors.toList());
                break;
            case CompareTypeConstants.DIFFERENT:
                break;
            default:
                break;
        }
        return result;
    }

    /**
     * @description 对比结果
     * @author zip.li
     * @date 2023/8/17 11:17
     * @Version1.0
     **/
    public Map<String, Object> compareResult(List<InfItemResult> list1, List<InfItemResult> list2, List<InfItemResult> sames) {
        List<String> diff = new ArrayList<>();
        List<String> common = new ArrayList<>();
        for (InfItemResult item : sames) {
            InfItemResult compare1 = new InfItemResult();
            InfItemResult compare2 = new InfItemResult();
            for (InfItemResult infItemResult : list1) {
                if (infItemResult.getInfId().equals(item.getInfId())) {
                    compare1 = infItemResult;
                }
            }
            for (InfItemResult infItemResult : list2) {
                if (infItemResult.getInfId().equals(item.getInfId())) {
                    compare2 = infItemResult;
                }
            }

//            List<InfResult> filteredPersons = list1.stream()
//                    .filter(infResult -> infResult.getInfId().equals(item.getInfId()))
//                    .collect(Collectors.toList());

            try {
                // zip.li update at 2023/10/31 特殊处理登录接口
                if ("6".equals(compare1.getInfId()) && "6".equals(compare2.getInfId())) {
                    common.add(item.getInfId());
                    continue;
                }
                ResponseVo res1 = JSONObject.parseObject(compare1.getResult(), ResponseVo.class);
                ResponseVo res2 = JSONObject.parseObject(compare2.getResult(), ResponseVo.class);

                if (res1.getCode() == res2.getCode()) {
                    if (res1.getResult() instanceof JSONObject && res2.getResult() instanceof JSONObject) {
                        JSONObject result1 = (JSONObject) res1.getResult();
                        JSONObject result2 = (JSONObject) res2.getResult();
                        boolean equals = result1.equals(result2);

                        if (equals) {
                            common.add(item.getInfId());
                        } else {
                            diff.add(item.getInfId());
                        }
                    } else if (res1.getResult() instanceof JSONArray && res2.getResult() instanceof JSONArray) {
                        JSONArray result1 = (JSONArray) res1.getResult();
                        JSONArray result2 = (JSONArray) res2.getResult();
                        if (result1.size() != result2.size()) {
                            diff.add(item.getInfId());
                        } else {
                            boolean flag = false;
                            outer:
                            for (int i = 0; i <= result1.size(); i++) {
                                for (int j = 0; j <= result2.size(); i++) {
                                    if (result1.get(i).equals(result2.get(j))) {
                                        flag = true;
                                        break outer;
                                    } else {
                                        flag = false;
                                    }
                                }
                            }
                            if (flag) {
                                common.add(item.getInfId());
                            } else {
                                diff.add(item.getInfId());
                            }
                        }
                    } else if (res1.getResult() instanceof String && res2.getResult() instanceof String) {
                        JSONObject result1 = JSONObject.parse((String) res1.getResult());
                        JSONObject result2 = JSONObject.parse((String) res2.getResult());
                        boolean equals = result1.equals(result2);

                        if (equals) {
                            common.add(item.getInfId());
                        } else {
                            diff.add(item.getInfId());
                        }
                    } else if (res1.getResult() == null && res2.getResult() == null) {
                        common.add(item.getInfId());
                    } else {
                        diff.add(item.getInfId());
                    }
                } else {
                    diff.add(item.getInfId());
                }
            } catch (Exception e) {
                boolean equals = compare1.getResult().equals(compare2.getResult());
                if (equals) {
                    common.add(item.getInfId());
                } else {
                    diff.add(item.getInfId());
                }
            }
        }
        Map<String, Object> map = new HashMap<>();
        if (diff.size() > 0) {
            map.put("different", diff);
        }
        if (common.size() > 0) {
            map.put("same", common);
        }
        return map;
    }

    @GetMapping("/getInfResult.action/{id}")
    @PreAuthorize("@ss.hasPermi('testmanage:compareResult:getInfResult')")
    public ResponseVo getInfResult(@PathVariable String id) {
        ArrayList<String> ids = new ArrayList<>();
        ids.add(id);

        List<SstReportItem> items = infReportService.queryReportItemByIds(ids);

        try {
            for (SstReportItem item : items) {
                JSONArray objects = JSON.parseArray(item.getResult());
                List<InfItemResult> infItemResults = objects.toJavaList(InfItemResult.class);
                item.setList(infItemResults);
            }
        } catch (Exception e) {
            return ResponseVo.failure("结果格式转换错误");
        }
        List<InfItemResult> results = items.get(0).getList();
        List<String> collect = results.stream().map(InfItemResult::getInfId)
                .collect(Collectors.toList());

        Map<String, InfItemResult> infMap = new HashMap<>();
        for (InfItemResult result : results) {
            infMap.put(result.getInfId(), result);
        }

        List<SstInf> list = infManageService.selectInfListByIds(collect);
        for (SstInf sstInf : list) {
            InfItemResult result = infMap.get(sstInf.getInfId());
            sstInf.setResult(result.getStatus());
            ReportItem reportItem = new ReportItem();
            reportItem.setReportName(items.get(0).getReportName());
            reportItem.setVersion(items.get(0).getReportVersion());
            reportItem.setResult(result.getResult());
            sstInf.setResultView(reportItem);
        }
        return ResponseVo.success(list);
    }
}
